/*
 * Copyright (c) 2014 Strong Group - 版权所有
 * 
 * This software is the confidential and proprietary information of
 * Strong Group. You shall not disclose such confidential information 
 * and shall use it only in accordance with the terms of the license 
 * agreement you entered into with www.cnstrong.cn.
 */
package com.zuorenke.serialize.support.json;

import java.io.BufferedReader;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.lang.reflect.Type;
import java.text.SimpleDateFormat;
import java.util.Map;
import java.util.TimeZone;

import com.zuorenke.help.SimpleFormatString;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonParser.Feature;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import com.zuorenke.serialize.ObjectInput;

/**
 *
 * 描述:
 *
 * @author  WQB
 * @created 2014-4-7 上午10:05:52
 * @since   v1.0.0
 */
public class JacksonObjectInput implements ObjectInput {

	private static String dateTimeFormate = SimpleFormatString.DATETIME_FORMAT;

	private final BufferedReader reader;

	private static ObjectMapper mapper = null;
	static {
		if (mapper == null) {
			JsonFactory factory = new JsonFactory();
			mapper = new ObjectMapper(factory);
			
			mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
			mapper.configure(Feature.ALLOW_UNQUOTED_CONTROL_CHARS,true);
			//配置允许单引号
			mapper.configure(Feature.ALLOW_SINGLE_QUOTES,true);
			//配置允许key不加引号
			mapper.configure(Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
			mapper.getSerializationConfig().with(new SimpleDateFormat(dateTimeFormate));
			mapper.getDeserializationConfig().with(new SimpleDateFormat(dateTimeFormate));
			mapper.setTimeZone(TimeZone.getDefault());
		}
	}

	public JacksonObjectInput(InputStream in) {
		this(new InputStreamReader(in));
	}

	public JacksonObjectInput(Reader reader) {
		this.reader = new BufferedReader(reader);
	}

	public boolean readBool() throws IOException {
		try {
			return readObject(boolean.class);
		} catch (ClassNotFoundException e) {
			throw new IOException(e.getMessage());
		}
	}

	public byte readByte() throws IOException {
		try {
			return readObject(byte.class);
		} catch (ClassNotFoundException e) {
			throw new IOException(e.getMessage());
		}
	}

	public short readShort() throws IOException {
		try {
			return readObject(short.class);
		} catch (ClassNotFoundException e) {
			throw new IOException(e.getMessage());
		}
	}

	public int readInt() throws IOException {
		try {
			return readObject(int.class);
		} catch (ClassNotFoundException e) {
			throw new IOException(e.getMessage());
		}
	}

	public long readLong() throws IOException {
		try {
			return readObject(long.class);
		} catch (ClassNotFoundException e) {
			throw new IOException(e.getMessage());
		}
	}

	public float readFloat() throws IOException {
		try {
			return readObject(float.class);
		} catch (ClassNotFoundException e) {
			throw new IOException(e.getMessage());
		}
	}

	public double readDouble() throws IOException {
		try {
			return readObject(double.class);
		} catch (ClassNotFoundException e) {
			throw new IOException(e.getMessage());
		}
	}

	public String readUTF() throws IOException {
		try {
			return readObject(String.class);
		} catch (ClassNotFoundException e) {
			throw new IOException(e.getMessage());
		}
	}

	public byte[] readBytes() throws IOException {
		return readLine().getBytes();
	}

	public Object readObject() throws IOException, ClassNotFoundException {
		String json = readLine();
		try {
			if (json.startsWith("{")) {
				return mapper.readValue(json, Map.class);
			} else {
				json = "{\"value\":" + json + "}";

				@SuppressWarnings("unchecked")
				Map<String, Object> map = mapper.readValue(json, Map.class);
				return map.get("value");
			}
		} catch (JsonMappingException |JsonParseException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

		return null;
	}

	public <T> T readObject(Class<T> cls) throws IOException, ClassNotFoundException {
		String json = readLine();
		try {
			return (T) mapper.readValue(json, cls);
		} catch (JsonMappingException | JsonParseException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

		return null;
	}
	
	public <T> T readObject(Class<T> cls, Type type) throws IOException, ClassNotFoundException {
		return readObject(cls);
	}

	private String readLine() throws IOException {
		String line = reader.readLine();
		if (line == null || line.trim().length() == 0)
			throw new EOFException();
		return line;
	}

	@SuppressWarnings("unchecked")
	@Override
	public <T> T readObject(TypeReference<?> valueTypeRef) throws IOException, ClassNotFoundException {
		String json = readLine();
		try {
			return mapper.readValue(json, valueTypeRef);
		} catch (JsonParseException |JsonMappingException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

		return null;
	}

}